<?php
/**
 * 本文件用于与lucene服务器进行查询
 *
 * <code>
 *    $cond = new UCLibLuceneCondition();
 *    $cond->addTerm("name", "中国");
 *    $cond->addTerm("gender", "1");
 *    $searcher = new UCLibLuceneApi();
 *    $searcher->addServer("localhost", 8080);
 *    var_dump($searcher->search($cond));
 * </code>
 * 
 * @author    徐鹏程 <xupengcheng@snda.com>
 * @version   0.0.1		2010/03/29
 * @note	1、	可以添加多台服务器，采用随机轮询
			2、	返回类型采用JSON
 */

require_once(dirname(__FILE__).'/UCFuncUtils.php');
require_once(dirname(__FILE__).'/UCLibCache.php');
require_once(dirname(__FILE__).'/UCLibLogger.php');
require_once(dirname(__FILE__).'/../config/UCConfSearch.php');


define('UC_SE_EXPIRE_TIME_1', 20); // 第一页
define('UC_SE_EXPIRE_TIME_2', 20); // 其他
define('UC_SE_CHANNEL_NAME','search'); //memcache分配的频道名
#define('UC_SE_DISABLE_CACHE', 1); //是否禁止cache

/**
 * UCLibLuceneApi 搜索接口定义
 */
class UCLibLuceneApi{
	private $_servers;

	/**
	 * 构造函数
	 */
	function __construct() {
		$this->_servers = UCConfSearch::getServers();
	}
	
	
	/**
	 * 添加一个服务器
	 * @param ip: 服务器地址
	 * @param port: 服务器端口
	 */
	public function addServer($host, $port) {
		$this->_servers []= array($host, $port);
	}

	/**
	 * 进行一次搜索
	 * @param condition: 搜索条件
	 * @param start: 起始位置
	 * @param size: 结果长度
	 * @return 结果是一个array,如果出错，返回false
	 *     array如下
	 *        "total" => 990, // 命中数
	 *        "total_estimate" => 1022, // 估计的总命中数
	 *        "time" => 79, // 处理时间，单位毫秒
	 *        "error" => 0, // 错误代码，0为没有错误
	 *        "start" => 0, // 起始位置
	 *        "length" => 20, // 数据条目
	 *        "query" => "+name:xxx +gender:1", // query
	 *        "result" => array(20) { // 命中结果
	 *            [0]=>
	 *            object(stdClass)#4 (1) {
	 *              ["user_id"]=>
	 *              string(5) "17352"
	 *            }
	 *            [1]=>
	 *            object(stdClass)#5 (1) {
	 *              ["user_id"]=>
	 *              string(5) "86499"
	 *            }
	 *         ... ... ... ...
	 */
	public function search($condition, $start = 0, $size = 20) {
		$param = $condition->toQuery();
		if ($start > 0) $param .= "&s=".$start;
		if ($size != 20) $param .= "&p=".$size;

		$result = false;
		$_time_start = microtime(true);
		if (!defined("UC_SE_DISABLE_CACHE")) {
			$cache = new UCLibCache(UC_SE_CHANNEL_NAME, false);
			$result = $cache->read(md5($param));
			if ($result) $result = json_decode($result, true);
		}

		if ($result === false) {
			$cnt = count($this->_servers);
			$index = mt_rand(0, $cnt - 1);
			$i = 0;
			$result = false;
			$host = null;
			$port = null;
			while ($i < $cnt) {
				$host = $this->_servers[$index][0];
				$port = $this->_servers[$index][1];
				$url = "http://$host:$port/search";
				$result = get_http_data($url, array("post" => $param), '', 0, 5);
				if ($result) $result = json_decode($result, true);
				if ($result) break;
				$i += 1;
				$index = ($index + 1) % $cnt;
			}
			if (!defined("UC_SE_DISABLE_CACHE")) {
				if (!($result === false)) {
					$cache->write(md5($param), json_encode($result), 300);
				}
			}
			UCLibLogger::rpc($param, microtime(true) - $_time_start, $host, $port, UCLIB_LOG_RPC_TYPE_SEARCH);
		} else {
			$result["source"] = "cache";
			$result["time"] = intval(1000 * (microtime(true) - $_time_start));
		}
		if (!defined("UC_SE_DISABLE_CACHE")) {
			$cache->close();
		}
		if ($result && !isset($result["result"])) $result["result"] = array();
		return $result;
	}
}

/*
$cond = new UCLibLuceneCondition();
$cond->addTerm("name", "中国");
$cond->addTerm("gender", "1");

$searcher = new UCLibLuceneApi();
$searcher->addServer("localhost", 8080);
var_dump($searcher->search($cond));
*/